package com.yonyou.wdt.job;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.yonyou.wdt.dao.JobLogDao;
import com.yonyou.wdt.entity.OpenApiURLEnum;
import com.yonyou.wdt.entity.QueryDto;
import com.yonyou.wdt.job.config.BaseConfig;
import com.yonyou.wdt.model.JobLogModel;
import com.yonyou.wdt.service.CommonService;
import com.yonyou.wdt.service.YonsuiteService;
import com.yonyou.wdt.utils.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * @ClassName YsProductToRedisJob
 * @Description 旺店通采购单数据同步至YonSuite请购单
 * @Author HuangWb
 * @Date 2023/5/12 18:35
 * @Version 1.0
 */
@Component
public class WdtPurchaseOrderToYsApplyOrderJob extends BaseConfig {

    private final WdtConfigProperties configProperties;

    private static Logger logger = LoggerFactory.getLogger(WdtPurchaseOrderToYsApplyOrderJob.class);
    @Resource
    public JobLogDao jobLogDao;
    @Resource
    private YonsuiteService yonsuiteService;
    @Resource
    private CommonService commonService;

    @Autowired
    public WdtPurchaseOrderToYsApplyOrderJob(WdtConfigProperties configProperties) {
        this.configProperties = configProperties;
    }

    @XxlJob("WdtPurchaseOrderToYsApplyOrderJob")
    public ReturnT<String> wdtPurchaseOrderToYsApplyOrderJob(String params) throws Exception {
        String param = XxlJobHelper.getJobParam();
        Map<String, Object> map = new HashMap<>();
        if (param != null && !"".equals(param)) {
            List<String> timeRange = Arrays.asList(param.split("\\|"));
            if (timeRange.size() == 2) {
                map.put("Start", timeRange.get(0));
                map.put("End", timeRange.get(1));
            } else {
                map.put("purchase_no", timeRange.get(0));
            }
        } else {
            // 默认查询前一天的数据
            map.put("Start", DateUtils.getStartDateBy10m());
            map.put("End", DateUtils.getEndDateBy10m());
        }
        String dateStr = null;
        if (map.get("Start") != null && map.get("End") != null) {
            dateStr = map.get("Start").toString() + map.get("End").toString();
        }
        // 处理相关业务
        QueryDto dto = new QueryDto();
        dto.setTenantId(getYsTenantId());
        dto.setAppKey(getYsAppKey());
        dto.setAppSecret(getYsAppSecret());
        // 获取YS系统租户动态域名信息
        ReturnT<String> isReturn2 = getYsDynamicDomainName(dto);
        // 域名获取失败
        if (isReturn2 != null) return isReturn2;
        try {
            List<JSONObject> responseList = sendWdt(map);
            Integer successCount = 0;
            Integer failCount = 0;
            // 解析数据，组装YS请求参数
            if (!responseList.isEmpty()) {
                HashMap<String, String> staffData = getStaffData(dto, yonsuiteService);
                HashMap<String, String> venderData = getVenderData(dto, yonsuiteService);
                for (int i = 0; i < responseList.size(); i++) {
                    JSONObject jsonObject = responseList.get(i);
                    //for (JSONObject jsonObject : responseList) {
                    Map<String, Object> ysSaveParam = assembleYsParams(jsonObject, dto, staffData, venderData);
                    if (ysSaveParam == null) {
                        failCount++;
                        continue;
                    }
                    JSONObject response = yonsuiteService.applySave(ysSaveParam, dto);
                    String wdtrefundNo = jsonObject.getStr("purchase_no");
                    if (null != response && "200".equals(response.getStr("code"))) {
                        successCount++;
                        logger.info("旺店通采购订单" + wdtrefundNo + "保存YS请购单" + response.getJSONObject("data").getStr("code") + "成功");
                        InsertLogger(wdtrefundNo, "1", "旺店通采购订单" + wdtrefundNo + "保存YS请购单" + response.getJSONObject("data").getStr("code") + "成功");
                    } else {
                        failCount++;
                        logger.error("旺店通采购订单" + wdtrefundNo + "保存YS请购单失败：{}", response.getOrDefault("message", ""));
                        InsertLogger(wdtrefundNo, "0", "旺店通采购订单" + wdtrefundNo + "保存YS请购单失败" + response.getOrDefault("message", "").toString());
                    }
                    // 处理YS接口调用频率问题
                    // 调用YS接口保存数据
                    this.APICurrentLimiting(OpenApiURLEnum.APPLY_SAVE, 19);
                }
                logger.info("当前时间段：{}至{} 需要同步到YS请购单数据有：{}条", map.get("Start"), map.get("End"), responseList.size());
            }
            Thread.sleep(1000);
            InsertLogger(null, "0", "旺店通采购订单一共" + responseList.size() + "条,保存YS请购单成功:" + successCount + "条，失败:" + failCount + "条。");

        } catch (Exception e) {
            logger.error("Error occurred", e);
            logger.error("旺店通采购订单同步YS请购单失败，{}", e.getMessage());
            InsertLogger(null, "0", "旺店通采购订单同步YS请购单失败" + e.getMessage());
            return ReturnT.FAIL;
        }
        logger.info("  --  旺店通采购订单同步YS请购单任务执行完成  --  ");
        return ReturnT.SUCCESS;
    }

    private HashMap<String, String> getVenderData(QueryDto dto, YonsuiteService yonsuiteService) throws Exception {
        // 1、员工列表查询，查询出所有员工，将name与id拼装成一个map集合，进行比对判断
        HashMap<String, Object> queryMap = new HashMap<>();  // 员工档案列表查询请求参数Map
        ArrayList<JSONObject> venderList = new ArrayList<>();  // 员工档案列表查询返回值
        Integer pageSize = 500;
        int pageIndex = 1;
        while (true) {
            queryMap.put("pageIndex", pageIndex);
            queryMap.put("pageSize", pageSize);
            queryMap.put("vendorApplyRange_isCreator", true);
            queryMap.put("stopstatus", false);
            JSONObject staffJsonList = yonsuiteService.vendorListQuery(queryMap, dto);
            if (staffJsonList.getStr("code").equals("200")) {
                if (null != staffJsonList.getJSONObject("data") && null != staffJsonList.getJSONObject("data").getJSONArray("recordList")) {
                    JSONArray purJSONArray = staffJsonList.getJSONObject("data").getJSONArray("recordList");
                    List<JSONObject> venderJson = JSONUtil.toList(purJSONArray, JSONObject.class);
                    venderList.addAll(venderJson);
                }
            }
            if (staffJsonList.getJSONObject("data").getInt("pageCount") <= pageIndex && staffJsonList.getJSONObject("data").getJSONArray("recordList").size() < pageSize) {
                break;
            }
            pageIndex++;
        }
        logger.info("YS系统供应商档案查询完成共：{}个", venderList.size());
        HashMap<String, String> venderMap = new HashMap<>();
        for (JSONObject warehouseJson : venderList) {
            venderMap.put(warehouseJson.getStr("code"), warehouseJson.getStr("id"));
        }
        return venderMap;
    }

    /**
     * @return
     * @Author Huangwb
     * @Description 组装YS请求数据
     * @Date 14:34 2023/5/17
     * @Param
     **/
    private Map<String, Object> assembleYsParams(JSONObject jsonObject, QueryDto dto, HashMap<String, String> staffData, HashMap<String, String> venderData) throws Exception {
        Map<String, Object> saleReturnSaveMap = new HashMap<>();
        Map<String, Object> data = new HashMap<>();
        String orgCode = "10";
        String providerNo = jsonObject.getStr("provider_no");
        if (providerNo.equals("DS00001")) {
            orgCode = "10";
        } else if (!providerNo.equals("10")) {
            orgCode = "30";
        }
        // 添加表头
        String purchaseNo = jsonObject.getStr("purchase_no");
        saleReturnSaveMap.put("bustype", "HYA001");//交易类型编码或交易类型id
        saleReturnSaveMap.put("org_code", orgCode);//需求组织编码
        saleReturnSaveMap.put("code", purchaseNo);//需求组织编码


        saleReturnSaveMap.put("operator", staffData.get(jsonObject.getStr("purchaser_name")));//请购人

        saleReturnSaveMap.put("vouchdate", jsonObject.getStr("created"));//单据日期，格式为:yyyy-MM-dd HH:mm:ss

        saleReturnSaveMap.put("_status", "Insert");  // 操作标识
        saleReturnSaveMap.put("memo", jsonObject.getStr("remark"));  // 备注
        //saleReturnSaveMap.put("salesOrgId", 10);  // 操作标识
        HashMap<String, Object> defMap = new HashMap<>();
        defMap.put("E_07", jsonObject.getStr("provider_name"));
        saleReturnSaveMap.put("applyOrderDefineCharacter", defMap);  // 操作标识

        JSONArray items = jsonObject.getJSONArray("details_list");
        // ==========子表============
        JSONArray details = new JSONArray();
        BigDecimal payMoney = BigDecimal.ZERO;
        for (Object element : items) {
            JSONObject item = (JSONObject) element;
            String product = item.getStr("goods_no");
            JSONObject redisPrJson = (JSONObject) RedisUtils.get(dto.getTenantId() + ":product:" + product);
            if (redisPrJson == null) {
                // 保存同步错误日志，未找到对应物料档案信息
                commonService.proToRedis(product, dto);
                redisPrJson = (JSONObject) RedisUtils.get(dto.getTenantId() + ":product:" + product);
                if (redisPrJson == null) {
                    logger.error("存在未同步YS系统物料数据：{}，请同步后重试", product);
                    InsertLogger(jsonObject.getStr("refund_no"), "0", "存在未同步YS系统物料数据：" + product + "，请同步后重试");
                    return null;
                }

            }
            String unitId = redisPrJson.getStr("unitCode") != null ? redisPrJson.getStr("unitCode") : null;
            //String unitId = "无";
            if (unitId == null) {
                logger.error("售后单：" + jsonObject.getStr("refund_no") + "存在未维护单位物料，请维护后重试");
                InsertLogger(jsonObject.getStr("refund_no"), "0", "存在未维护单位物料，请维护后重试");
            }
            JSONObject saleReturnDetailsJson = new JSONObject();
            if (venderData.get(providerNo) != null) {
                // saleReturnDetailsJson.put("adviseSupplier_code", providerNo);//建议供应商编码
                saleReturnDetailsJson.put("vendor", venderData.get(providerNo));//建议供应商编码
            }
            saleReturnDetailsJson.set("product_cCode", product);//物料编码
            BigDecimal qty = item.getBigDecimal("num");
            saleReturnDetailsJson.set("subQty", qty);//采购数量
            saleReturnDetailsJson.set("purUOM_Code", unitId);//采购单位编码
            saleReturnDetailsJson.set("unit_code", unitId);//主计量编码
            saleReturnDetailsJson.set("qty", qty);//数量
            saleReturnDetailsJson.set("requirementDate", item.getStr("created"));//需求日期
            saleReturnDetailsJson.set("purchaseOrg_code", orgCode);//采购组织编码
            saleReturnDetailsJson.set("invExchRate", 1);//采购换算率，小数位数取自【我的企业】-【公共参数】中的参数“换算率精度”设置的取值。最多11位数，精度最多取8位
            saleReturnDetailsJson.set("_status", "Insert");  // 操作标识
            details.add(saleReturnDetailsJson);
        }
        saleReturnSaveMap.put("applyOrders", details);
        saleReturnSaveMap.put("resubmitCheckKey", UUID.randomUUID().toString().replace("-", ""));
        data.put("data", saleReturnSaveMap);
        //  ReSubmitUtil.resubmitCheckKey(data);
        return data;
    }

    public static HashMap<String, String> getStaffData(QueryDto dto, YonsuiteService yonsuiteService) throws Exception {
        // 1、员工列表查询，查询出所有员工，将name与id拼装成一个map集合，进行比对判断
        HashMap<String, Object> queryMap = new HashMap<>();  // 员工档案列表查询请求参数Map
        ArrayList<JSONObject> staffList = new ArrayList<>();  // 员工档案列表查询返回值
        int pageIndex = 1;
        while (true) {
            queryMap.put("index", pageIndex);
            queryMap.put("size", 100);
            JSONObject staffJsonList = yonsuiteService.staffListQuery(queryMap, dto);
            if (staffJsonList.getStr("code").equals("200")) {
                if (null != staffJsonList.getJSONObject("data") && null != staffJsonList.getJSONObject("data").getJSONArray("content")) {
                    JSONArray purJSONArray = staffJsonList.getJSONObject("data").getJSONArray("content");
                    for (Object warehouse : purJSONArray) {
                        JSONObject warehouseJson = JSONUtil.parseObj(warehouse);
                        staffList.add(warehouseJson);
                    }
                }
            }
            if (staffJsonList.getJSONObject("data").getInt("totalPages") <= pageIndex && staffJsonList.getJSONObject("data").getJSONArray("content").size() < 100) {
                break;
            }
            pageIndex++;
        }
        logger.info("YS系统员工档案查询完成共：{}个", staffList.size());
        HashMap<String, String> staffMap = new HashMap<>();
        for (JSONObject warehouseJson : staffList) {
            staffMap.put(warehouseJson.getStr("name"), warehouseJson.getStr("id"));
        }
        return staffMap;
    }

    /**
     * @Author Huangwb
     * @Description 查询YS系统租户动态域名信息
     * @Date 2023/10/30 15:45
     **/
    public ReturnT<String> getYsDynamicDomainName(QueryDto ysQueryDto) {
        try {
            String tenantId = ysQueryDto.getTenantId();  // 租户ID
            if (RedisUtils.get(tenantId + ":DynamicDomainName") == null) {
                // 根据租户ID查询动态域名
                JSONObject dynamicDomainName = yonsuiteService.getDynamicDomainName(null, tenantId);
                if (null != dynamicDomainName && !dynamicDomainName.isEmpty()) {
                    // 将动态域名存入Redis
                    RedisUtils.set(tenantId + ":DynamicDomainName", dynamicDomainName, 86400 * 30);
                } else {
                    logger.error("查询租户【{}】动态域名失败，请重试", tenantId);
                    // insertXxlJobLog(null, "0", "租户：【" + tenantId + "】获取动态域名失败，请稍后重试", jobClassType);
                    InsertLogger(null, "0", "获取动态域名失败");
                    return new ReturnT<>(ReturnT.FAIL_CODE, "查询租户【" + tenantId + "】动态域名失败，请重试");
                }
            }
            // 获取Redis中指定租户动态域名
            JSONObject dynamicDomainNameRedis = (JSONObject) RedisUtils.get(tenantId + ":DynamicDomainName");
            ysQueryDto.setGatewayUrl(dynamicDomainNameRedis.getStr("gatewayUrl"));
            ysQueryDto.setTokenUrl(dynamicDomainNameRedis.getStr("tokenUrl"));
            return null;
        } catch (Exception e) {
            return new ReturnT<>(ReturnT.FAIL_CODE, "获取动态域名失败：" + e.getMessage());
        }
    }

    private List<JSONObject> sendWdt(Map<String, Object> map) {
        String apiUrl = "purchase_order_query.php";
        List<JSONObject> resList = new ArrayList<>();
        WdtClient client = new WdtClient(configProperties.getSid(), configProperties.getKey(), configProperties.getSecret(), configProperties.getUrl());
        Integer realityPageNo = 0;
        map.put("page_no", realityPageNo.toString());
        map.put("page_size", "100");
        if (map.get("purchase_no") == null) {
            map.put("start_time", map.get("Start"));
            map.put("end_time", map.get("End"));
            map.remove("Start");
            map.remove("End");
            //map.put("status", 90);
        }
        boolean hasNext = true;
        //总页数
        Integer totalPage = 0;
        //总条数
        Integer total_count = 0;
        while (hasNext) {
            map.put("page_no", realityPageNo.toString());
            String res = null;
            try {
                res = client.execute(apiUrl, map);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            JSONObject saleOutJson = JSONUtil.parseObj(res);
            if ("0".equals(saleOutJson.getStr("code"))) {
                //判断分页
                if (realityPageNo == 0) {
                    total_count = saleOutJson.getInt("total_count", 0);
                    totalPage = total_count % 100 == 0 ? total_count / 100 : total_count / 100 + 1;
                }
                //每页订单列表
                JSONArray orderArray = saleOutJson.getJSONArray("purchase_list");
                if (orderArray.size() > 0) {
                    resList.addAll(JSONUtil.toList(orderArray, JSONObject.class));
                }
                //判断分页
                if (realityPageNo == 0) {
                    total_count = saleOutJson.getInt("total_count", 0);
                    totalPage = total_count % 100 == 0 ? total_count / 100 : total_count / 100 + 1;
                }
                if (totalPage > realityPageNo + 1) {
                    realityPageNo += 1;
                } else {
                    hasNext = false;
                }
            } else {
                InsertLogger(null, "0", "旺店通采购订单接口查询失败" + saleOutJson.getStr("message"));
                break;
            }
        }
        return resList;
    }

    /**
     * @return
     * @Author Huangwb
     * @Description 插入数据库日志信息
     * @Date 10:30 2023/9/14
     * @Param
     **/
    private void InsertLogger(String code, String oneL, String mags) {  // 单据编号、是否成功、详细信息
        try {
            JobLogModel jobLogDTO = new JobLogModel();
            jobLogDTO.setJobClass("HYZM006");
            jobLogDTO.setJobCode(code);
            jobLogDTO.setJobTime(new Date());
            jobLogDTO.setJobResult(oneL);
            jobLogDTO.setJobResultMessage(mags);
            jobLogDTO.setJobLogUser("dxroot");
            jobLogDao.insertJobLog(jobLogDTO);
        } catch (Exception e) {
            logger.error("插入日志错误：" + e.getMessage());
        }
    }

}
